home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / f_smoother.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  25.0 KB  |  1,290 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include <math.h>
  19. #include <assert.h>
  20. #include <crtdbg.h>
  21. #include <stdio.h>
  22. #include <windows.h>
  23. #include <commctrl.h>
  24.  
  25. #include "resource.h"
  26.  
  27. #include "filter.h"
  28. #include "cpuaccel.h"
  29. #include "ScriptInterpreter.h"
  30. #include "ScriptValue.h"
  31. #include "ScriptError.h"
  32. #include "e_blur.h"
  33. #include "effect.h"
  34.  
  35. ///////////////////////////////////////////////////////////////////////////
  36.  
  37. #define USE_ASM
  38.  
  39. extern HINSTANCE g_hInst;
  40.  
  41. ///////////////////////////////////////////////////////////////////////////
  42.  
  43. typedef unsigned char byte;
  44.  
  45. typedef struct MyFilterData {
  46.     IFilterPreview *ifp;
  47.     int        grad_threshold;
  48.     byte    *sum_row[5];
  49.     Pixel    *avg_row[5];
  50.     VBitmap    vbBlur;
  51.     VEffect    *effBlur;
  52.     void    *pBlurBitmap;
  53.     bool    fBlurPass;
  54. } MyFilterData;
  55.  
  56. static int *square_table;
  57. static int init_count = 0;
  58.  
  59.     // codes[i] = yyy000xx
  60.     //
  61.     // y = # of bits set in bits 0-4 of i
  62.     // x = # of bits set in bits 1-3 of i
  63.  
  64. static const byte codes[]={
  65.     0x00, 0x20, 0x21, 0x41, 0x21, 0x41, 0x42, 0x62,
  66.     0x21, 0x41, 0x42, 0x62, 0x42, 0x62, 0x63, 0x83,
  67.     0x20, 0x40, 0x41, 0x61, 0x41, 0x61, 0x62, 0x82,
  68.     0x41, 0x61, 0x62, 0x82, 0x62, 0x82, 0x83, 0xa3,
  69. };
  70.  
  71. static void __declspec(naked) filtrow_1_mmx(byte *sum, Pixel *src, long width, const long pitch, const long thresh) {
  72.     __asm {
  73.         push    ebx
  74.         push    esi
  75.         push    edi
  76.         push    ebp
  77.  
  78.         mov            edi,[esp+16+4]
  79.         mov            esi,[esp+16+8]
  80.         mov            ebp,[esp+16+12]
  81.         mov            edx,[esp+16+16]
  82.         mov            ecx,[esp+16+20]
  83.  
  84.         sub            esi,edx
  85.  
  86.         neg            ecx
  87.         add            edi,ebp
  88.         neg            ebp
  89.         pxor        mm7,mm7
  90. pixelloop:
  91.         movd        mm0,[esi]
  92.  
  93.         movd        mm2,[esi+edx*2]
  94.         punpcklbw    mm0,mm7
  95.  
  96.         movd        mm1,[esi+edx-4]
  97.         punpcklbw    mm2,mm7
  98.  
  99.         movd        mm3,[esi+edx+4]
  100.         punpcklbw    mm1,mm7
  101.  
  102.         psubw        mm0,mm2
  103.         punpcklbw    mm3,mm7
  104.  
  105.         movq        mm2,mm0
  106.         psraw        mm0,15
  107.  
  108.         pxor        mm2,mm0
  109.         paddw        mm2,mm0
  110.  
  111.         movq        mm0,mm2
  112.         psubw        mm1,mm3
  113.  
  114.         movq        mm3,mm1
  115.         psraw        mm1,15
  116.  
  117.         pxor        mm3,mm1
  118.         paddw        mm3,mm1
  119.  
  120.         movq        mm1,mm3
  121.         psllq        mm2,16
  122.  
  123.         movq        mm4,mm0
  124.         psllq        mm3,16
  125.  
  126.  
  127.         movq        mm5,mm1
  128.         psllq        mm4,32
  129.  
  130.         psllq        mm5,32
  131.         paddw        mm0,mm2
  132.  
  133.         paddw        mm1,mm3
  134.         paddw        mm0,mm4
  135.  
  136.         paddw        mm1,mm5
  137.         punpckhwd    mm0,mm0
  138.  
  139.         pmaddwd        mm0,mm0
  140.         add            esi,4
  141.  
  142.         movd        eax,mm0
  143.         add            eax,ecx
  144.         adc            ebx,ebx
  145.         and            ebx,31
  146.         mov            al,[codes + ebx]
  147.         mov            [edi+ebp],al
  148.  
  149.         inc            ebp
  150.         jne            pixelloop
  151.  
  152.         shr            ebx,1
  153.         mov            al,[codes + ebx]
  154.         mov            [edi],al
  155.         shr            ebx,1
  156.         mov            al,[codes + ebx]
  157.         mov            [edi+1],al
  158.  
  159.         pop        ebp
  160.         pop        edi
  161.         pop        esi
  162.         pop        ebx
  163.  
  164.         ret
  165.     }
  166. }
  167.  
  168. static void filtrow_1(byte *sum, Pixel *src, long width, const long pitch, const long thresh) {
  169.     if (MMX_enabled) {
  170.         filtrow_1_mmx(sum, src, width, pitch, thresh);
  171.         return;
  172.     }
  173.  
  174.     long bitarray=0;
  175.     long bitarray2=0;
  176.  
  177.     src = (Pixel *)((char *)src - pitch);
  178.  
  179.     do {
  180.         Pixel pu, pd, pl, pr;
  181.         int grad_x, grad_y;
  182.  
  183.         // Fetch surrounding pixels.
  184.  
  185. #if 0
  186.         pl = src[-1];
  187.         pr = src[1];
  188.         pu = *(Pixel *)((char *)src - pitch);
  189.         pd = *(Pixel *)((char *)src + pitch);
  190. #else
  191.         pl = *(Pixel *)((char *)(src-1) + pitch);
  192.         pr = *(Pixel *)((char *)(src+1) + pitch);
  193.         pu = *(Pixel *)((char *)src);
  194.         pd = *(Pixel *)((char *)src + pitch*2);
  195. #endif
  196.  
  197.         // Compute gradient at pixel.
  198.  
  199. #if 0
  200.         grad_x    = ((((int)pr&0xff0000) - ((int)pl&0xff0000))>>16)
  201.                 + ((((int)pr&0x00ff00) - ((int)pl&0x00ff00))>> 8)
  202.                 + ((((int)pr&0x0000ff) - ((int)pl&0x0000ff))    );
  203.  
  204.         grad_y    = ((((int)pd&0xff0000) - ((int)pu&0xff0000))>>16)
  205.                 + ((((int)pd&0x00ff00) - ((int)pu&0x00ff00))>> 8)
  206.                 + ((((int)pd&0x0000ff) - ((int)pu&0x0000ff))    );
  207. #elif 0
  208.         grad_x    = abs((((int)pr&0xff0000) - ((int)pl&0xff0000))>>16)
  209.                 + abs((((int)pr&0x00ff00) - ((int)pl&0x00ff00))>> 8)
  210.                 + abs((((int)pr&0x0000ff) - ((int)pl&0x0000ff))    );
  211.  
  212.         grad_y    = abs((((int)pd&0xff0000) - ((int)pu&0xff0000))>>16)
  213.                 + abs((((int)pd&0x00ff00) - ((int)pu&0x00ff00))>> 8)
  214.                 + abs((((int)pd&0x0000ff) - ((int)pu&0x0000ff))    );
  215. #else
  216.         Pixel x1 = ((pr&0xff00ff)+0x00000100) - (pl&0xff00ff);
  217.         Pixel x2 = (pr&0x00ff00) - (pl&0x00ff00);
  218.         Pixel y1 = ((pd&0xff00ff)+0x00000100) - (pu&0xff00ff);
  219.         Pixel y2 = (pd&0x00ff00) - (pu&0x00ff00);
  220.  
  221.         grad_x = (((int)(x1 + (x1<<16)) - 0x01000000) >> 16) + ((int)x2>>8);
  222.         grad_y = (((int)(y1 + (y1<<16)) - 0x01000000) >> 16) + ((int)y2>>8);
  223. #endif
  224.  
  225.         bitarray >>= 1;
  226.  
  227. //        if (grad_x*grad_x + grad_y*grad_y > thresh) {
  228.         if (square_table[765+grad_x] + square_table[765+grad_y] > thresh) {
  229.             bitarray |= 16;
  230.         }
  231.  
  232.         *sum++ = codes[bitarray];
  233.  
  234.         ++src;
  235.     } while(--width>0);
  236.  
  237.     *sum++ = codes[bitarray>>1];
  238.     *sum++ = codes[bitarray>>2];
  239. }
  240.  
  241. static void __declspec(naked) avgrow_asm(Pixel *dst, Pixel *src, long width) {
  242.     __asm {
  243.         push    ebx
  244.         push    esi
  245.         push    edi
  246.         push    ebp
  247.  
  248.         mov        esi,[esp+8+16]
  249.         mov        edi,[esp+4+16]
  250.  
  251.         mov        eax,[esi]
  252.         mov        ebx,0000ff00h
  253.         and        ebx,eax
  254.         and        eax,00ff00ffh
  255.  
  256.         mov        ecx,[esi+4]
  257.         mov        edx,0000ff00h
  258.  
  259.         lea        eax,[eax+eax*4]
  260.         lea        ebx,[ebx+ebx*4]
  261.  
  262.         and        edx,ecx
  263.         and        ecx,00ff00ffh
  264.         add        edx,edx
  265.         add        ecx,ecx
  266.         add        ebx,edx
  267.         add        eax,ecx
  268.  
  269.         mov        ecx,[esi+8]
  270.         mov        edx,0000ff00h
  271.         and        edx,ecx
  272.         and        ecx,00ff00ffh
  273.         add        ebx,edx
  274.         add        eax,ecx
  275.  
  276.         add        eax,00040004h
  277.         add        ebx,00000400h
  278.  
  279.         shr        eax,3
  280.         shr        ebx,3
  281.  
  282.         and        eax,00ff00ffh
  283.         and        ebx,0000ff00h
  284.  
  285.         add        eax,ebx
  286.  
  287.         mov        [edi],eax
  288.  
  289.  
  290.  
  291.  
  292.         mov        eax,[esi+4]
  293.         mov        ebx,0000ff00h
  294.         and        ebx,eax
  295.         and        eax,00ff00ffh
  296.  
  297.         mov        ecx,[esi+8]
  298.         mov        edx,0000ff00h
  299.         and        edx,ecx
  300.         and        ecx,00ff00ffh
  301.         add        ebx,edx
  302.         add        eax,ecx
  303.  
  304.         mov        ecx,[esi]
  305.         mov        edx,0000ff00h
  306.         and        edx,ecx
  307.         and        ecx,00ff00ffh
  308.  
  309.         add        eax,eax
  310.         add        ebx,ebx
  311.  
  312.         lea        edx,[edx+edx*2]
  313.         lea        ecx,[ecx+ecx*2]
  314.  
  315.         add        ebx,edx
  316.         add        eax,ecx
  317.  
  318.         mov        ecx,[esi+12]
  319.         mov        edx,0000ff00h
  320.         and        edx,ecx
  321.         and        ecx,00ff00ffh
  322.         add        ebx,edx
  323.         add        eax,ecx
  324.  
  325.         add        eax,00040004h
  326.         add        ebx,00000400h
  327.  
  328.         shr        eax,3
  329.         shr        ebx,3
  330.  
  331.         and        eax,00ff00ffh
  332.         and        ebx,0000ff00h
  333.  
  334.         add        eax,ebx
  335.  
  336.         mov        [edi+4],eax
  337.  
  338.         ;prepare for loop!
  339.  
  340.         mov        ebp,[esp+12+16]
  341.         sub        ebp,4
  342.         mov        eax,ebp
  343.         shl        eax,2
  344.         add        esi,eax
  345.         add        edi,eax
  346.         neg        ebp
  347.  
  348. pixelloop:
  349.         mov        eax,[esi+ebp*4+4]
  350.         mov        ebx,0000ff00h
  351.         and        ebx,eax
  352.         and        eax,00ff00ffh
  353.  
  354.         mov        ecx,[esi+ebp*4+8]
  355.         mov        edx,0000ff00h
  356.         and        edx,ecx
  357.         and        ecx,00ff00ffh
  358.         add        ebx,edx
  359.         add        eax,ecx
  360.  
  361.         mov        ecx,[esi+ebp*4+12]
  362.         mov        edx,0000ff00h
  363.         and        edx,ecx
  364.         and        ecx,00ff00ffh
  365.         add        ebx,edx
  366.         add        eax,ecx
  367.  
  368.         add        eax,eax
  369.         add        ebx,ebx
  370.  
  371.         mov        ecx,[esi+ebp*4]
  372.         mov        edx,0000ff00h
  373.         and        edx,ecx
  374.         and        ecx,00ff00ffh
  375.         add        ebx,edx
  376.         add        eax,ecx
  377.  
  378.         mov        ecx,[esi+ebp*4+16]
  379.         mov        edx,0000ff00h
  380.         and        edx,ecx
  381.         and        ecx,00ff00ffh
  382.         add        ebx,edx
  383.         add        eax,ecx
  384.  
  385.         add        eax,00040004h
  386.         add        ebx,00000400h
  387.  
  388.         shr        eax,3
  389.         shr        ebx,3
  390.  
  391.         and        eax,00ff00ffh
  392.         and        ebx,0000ff00h
  393.  
  394.         add        eax,ebx
  395.  
  396.         mov        [edi+ebp*4+8],eax
  397.  
  398.         inc        ebp
  399.         jne        pixelloop
  400.  
  401.         ;finish up
  402.  
  403.         mov        eax,[esi+8]
  404.         mov        ebx,0000ff00h
  405.         and        ebx,eax
  406.         and        eax,00ff00ffh
  407.  
  408.         mov        ecx,[esi+12]
  409.         mov        edx,0000ff00h
  410.         and        edx,ecx
  411.         and        ecx,00ff00ffh
  412.         add        ebx,edx
  413.         add        eax,ecx
  414.  
  415.         mov        ecx,[esi+16]
  416.         mov        edx,0000ff00h
  417.         and        edx,ecx
  418.         and        ecx,00ff00ffh
  419.         add        eax,eax
  420.         add        ebx,ebx
  421.         lea        edx,[edx+edx*2]
  422.         lea        ecx,[ecx+ecx*2]
  423.         add        ebx,edx
  424.         add        eax,ecx
  425.  
  426.         mov        ecx,[esi+4]
  427.         mov        edx,0000ff00h
  428.         and        edx,ecx
  429.         and        ecx,00ff00ffh
  430.         add        ebx,edx
  431.         add        eax,ecx
  432.  
  433.         add        eax,00040004h
  434.         add        ebx,00000400h
  435.  
  436.         shr        eax,3
  437.         shr        ebx,3
  438.  
  439.         and        eax,00ff00ffh
  440.         and        ebx,0000ff00h
  441.  
  442.         add        eax,ebx
  443.  
  444.         mov        [edi+8],eax
  445.  
  446.  
  447.  
  448.         mov        eax,[esi+16]
  449.         mov        ebx,0000ff00h
  450.         and        ebx,eax
  451.         and        eax,00ff00ffh
  452.  
  453.         mov        ecx,[esi+12]
  454.         mov        edx,0000ff00h
  455.         and        edx,ecx
  456.         and        ecx,00ff00ffh
  457.         lea        eax,[eax+eax*4]
  458.         lea        ebx,[ebx+ebx*4]
  459.         add        ecx,ecx
  460.         add        edx,edx
  461.         add        ebx,edx
  462.         add        eax,ecx
  463.  
  464.         mov        ecx,[esi+8]
  465.         mov        edx,0000ff00h
  466.         and        edx,ecx
  467.         and        ecx,00ff00ffh
  468.         add        ebx,edx
  469.         add        eax,ecx
  470.  
  471.         add        eax,00040004h
  472.         add        ebx,00000400h
  473.  
  474.         shr        eax,3
  475.         shr        ebx,3
  476.  
  477.         and        eax,00ff00ffh
  478.         and        ebx,0000ff00h
  479.  
  480.         add        eax,ebx
  481.  
  482.         mov        [edi+12],eax
  483.  
  484.         pop        ebp
  485.         pop        edi
  486.         pop        esi
  487.         pop        ebx
  488.  
  489.         ret
  490.     }
  491. }
  492.  
  493. static void __declspec(naked) avgrow_mmx(Pixel *dst, Pixel *src, long width) {
  494.     static __int64 add4=0x0004000400040004i64;
  495.     __asm {
  496.         push    ebx
  497.         push    esi
  498.         push    edi
  499.         push    ebp
  500.  
  501.         mov        esi,[esp+8+16]
  502.         mov        edi,[esp+4+16]
  503.  
  504.         mov        eax,[esi]
  505.         mov        ebx,0000ff00h
  506.         and        ebx,eax
  507.         and        eax,00ff00ffh
  508.  
  509.         mov        ecx,[esi+4]
  510.         mov        edx,0000ff00h
  511.  
  512.         lea        eax,[eax+eax*4]
  513.         lea        ebx,[ebx+ebx*4]
  514.  
  515.         and        edx,ecx
  516.         and        ecx,00ff00ffh
  517.         add        edx,edx
  518.         add        ecx,ecx
  519.         add        ebx,edx
  520.         add        eax,ecx
  521.  
  522.         mov        ecx,[esi+8]
  523.         mov        edx,0000ff00h
  524.         and        edx,ecx
  525.         and        ecx,00ff00ffh
  526.         add        ebx,edx
  527.         add        eax,ecx
  528.  
  529.         add        eax,00040004h
  530.         add        ebx,00000400h
  531.  
  532.         shr        eax,3
  533.         shr        ebx,3
  534.  
  535.         and        eax,00ff00ffh
  536.         and        ebx,0000ff00h
  537.  
  538.         add        eax,ebx
  539.  
  540.         mov        [edi],eax
  541.  
  542.  
  543.  
  544.  
  545.         mov        eax,[esi+4]
  546.         mov        ebx,0000ff00h
  547.         and        ebx,eax
  548.         and        eax,00ff00ffh
  549.  
  550.         mov        ecx,[esi+8]
  551.         mov        edx,0000ff00h
  552.         and        edx,ecx
  553.         and        ecx,00ff00ffh
  554.         add        ebx,edx
  555.         add        eax,ecx
  556.  
  557.         mov        ecx,[esi]
  558.         mov        edx,0000ff00h
  559.         and        edx,ecx
  560.         and        ecx,00ff00ffh
  561.  
  562.         add        eax,eax
  563.         add        ebx,ebx
  564.  
  565.         lea        edx,[edx+edx*2]
  566.         lea        ecx,[ecx+ecx*2]
  567.  
  568.         add        ebx,edx
  569.         add        eax,ecx
  570.  
  571.         mov        ecx,[esi+12]
  572.         mov        edx,0000ff00h
  573.         and        edx,ecx
  574.         and        ecx,00ff00ffh
  575.         add        ebx,edx
  576.         add        eax,ecx
  577.  
  578.         add        eax,00040004h
  579.         add        ebx,00000400h
  580.  
  581.         shr        eax,3
  582.         shr        ebx,3
  583.  
  584.         and        eax,00ff00ffh
  585.         and        ebx,0000ff00h
  586.  
  587.         add        eax,ebx
  588.  
  589.         mov        [edi+4],eax
  590.  
  591.         ;prepare for loop!
  592.  
  593.         mov        ebp,[esp+12+16]
  594.         sub        ebp,4
  595.         mov        eax,ebp
  596.         shl        eax,2
  597.         add        esi,eax
  598.         add        edi,eax
  599.         neg        ebp
  600.  
  601.         pxor        mm7,mm7
  602.         movq        mm6,add4
  603. pixelloop:
  604.         movd        mm0,[esi+ebp*4+4]
  605.         punpcklbw    mm0,mm7
  606.  
  607.         movd        mm1,[esi+ebp*4+8]
  608.         punpcklbw    mm1,mm7
  609.  
  610.         movd        mm2,[esi+ebp*4+12]
  611.         punpcklbw    mm2,mm7
  612.  
  613.         paddw        mm0,mm1
  614.         paddw        mm0,mm2
  615.         paddw        mm0,mm0
  616.  
  617.         movd        mm3,[esi+ebp*4]
  618.         punpcklbw    mm3,mm7
  619.  
  620.         movd        mm4,[esi+ebp*4+16]
  621.         punpcklbw    mm4,mm7
  622.  
  623.         paddw        mm3,mm4
  624.         paddw        mm0,mm3
  625.  
  626.         paddw        mm0,mm6
  627.         psraw        mm0,3
  628.         packuswb    mm0,mm0
  629.  
  630.         movd        [edi+ebp*4+8],mm0
  631.  
  632.         inc        ebp
  633.         jne        pixelloop
  634.  
  635.         ;finish up
  636.  
  637.         mov        eax,[esi+4]
  638.         mov        ebx,0000ff00h
  639.         and        ebx,eax
  640.         and        eax,00ff00ffh
  641.  
  642.         mov        ecx,[esi+8]
  643.         mov        edx,0000ff00h
  644.         and        edx,ecx
  645.         and        ecx,00ff00ffh
  646.         add        ebx,edx
  647.         add        eax,ecx
  648.  
  649.         mov        ecx,[esi+12]
  650.         mov        edx,0000ff00h
  651.         and        edx,ecx
  652.         and        ecx,00ff00ffh
  653.         add        eax,eax
  654.         add        ebx,ebx
  655.         lea        edx,[edx+edx*2]
  656.         lea        ecx,[ecx+ecx*2]
  657.         add        ebx,edx
  658.         add        eax,ecx
  659.  
  660.         mov        ecx,[esi]
  661.         mov        edx,0000ff00h
  662.         and        edx,ecx
  663.         and        ecx,00ff00ffh
  664.         add        ebx,edx
  665.         add        eax,ecx
  666.  
  667.         add        eax,00040004h
  668.         add        ebx,00000400h
  669.  
  670.         shr        eax,3
  671.         shr        ebx,3
  672.  
  673.         and        eax,00ff00ffh
  674.         and        ebx,0000ff00h
  675.  
  676.         add        eax,ebx
  677.  
  678.         mov        [edi+8],eax
  679.  
  680.  
  681.  
  682.         mov        eax,[esi+12]
  683.         mov        ebx,0000ff00h
  684.         and        ebx,eax
  685.         and        eax,00ff00ffh
  686.  
  687.         mov        ecx,[esi+8]
  688.         mov        edx,0000ff00h
  689.         and        edx,ecx
  690.         and        ecx,00ff00ffh
  691.         lea        eax,[eax+eax*4]
  692.         lea        ebx,[ebx+ebx*4]
  693.         add        ecx,ecx
  694.         add        edx,edx
  695.         add        ebx,edx
  696.         add        eax,ecx
  697.  
  698.         mov        ecx,[esi+4]
  699.         mov        edx,0000ff00h
  700.         and        edx,ecx
  701.         and        ecx,00ff00ffh
  702.         add        ebx,edx
  703.         add        eax,ecx
  704.  
  705.         add        eax,00040004h
  706.         add        ebx,00000400h
  707.  
  708.         shr        eax,3
  709.         shr        ebx,3
  710.  
  711.         and        eax,00ff00ffh
  712.         and        ebx,0000ff00h
  713.  
  714.         add        eax,ebx
  715.  
  716.         mov        [edi+12],eax
  717.  
  718.         pop        ebp
  719.         pop        edi
  720.         pop        esi
  721.         pop        ebx
  722.  
  723.         ret
  724.     }
  725. }
  726.  
  727. static void avgrow(Pixel *dst, Pixel *src, long width) {
  728. #ifdef USE_ASM
  729.  
  730.     if (MMX_enabled)
  731.         avgrow_mmx(dst, src, width);
  732.     else
  733.         avgrow_asm(dst, src, width);
  734.  
  735. #else
  736.  
  737.     int rsum, gsum, bsum, r0, g0, b0;
  738.     long w;
  739.  
  740.     Pixel c = *src++;
  741.  
  742.     r0 = ((int)(c>>16)&0xff);
  743.     g0 = ((int)(c>> 8)&0xff);
  744.     b0 = ((int)(c    )&0xff);
  745.  
  746.     rsum = r0*4;
  747.     gsum = g0*4;
  748.     bsum = b0*4;
  749.  
  750.     w=1;
  751.     do {
  752.         Pixel c = src[0];
  753.  
  754.         rsum = rsum + ((int)(c>>16)&0xff);
  755.         gsum = gsum + ((int)(c>> 8)&0xff);
  756.         bsum = bsum + ((int)(c    )&0xff);
  757.  
  758.         ++src;
  759.     } while(--w);
  760.  
  761.     w=3;
  762.     do {
  763.         Pixel c = src[0];
  764.  
  765.         rsum = rsum + ((int)(c>>16)&0xff) - r0;
  766.         gsum = gsum + ((int)(c>> 8)&0xff) - g0;
  767.         bsum = bsum + ((int)(c    )&0xff) - b0;
  768.  
  769.         *dst++ = ((rsum/5) << 16) | ((gsum/5)<<8) | (bsum/5);
  770.  
  771.         ++src;
  772.     } while(--w);
  773.  
  774.     w = width-6;
  775.     do {
  776.         Pixel c = src[0], d = src[-5];
  777.  
  778.         rsum = rsum + ((int)(c>>16)&0xff) - ((int)(d>>16)&0xff);
  779.         gsum = gsum + ((int)(c>> 8)&0xff) - ((int)(d>> 8)&0xff);
  780.         bsum = bsum + ((int)(c    )&0xff) - ((int)(d    )&0xff);
  781.  
  782.         *dst++ = ((rsum/5) << 16) | ((gsum/5)<<8) | (bsum/5);
  783.  
  784.         ++src;
  785.     } while(--w);
  786.  
  787.     c = *src++;
  788.  
  789.     r0 = ((int)(c>>16)&0xff);
  790.     g0 = ((int)(c>> 8)&0xff);
  791.     b0 = ((int)(c    )&0xff);
  792.  
  793.     w=3;
  794.     do {
  795.         Pixel d = src[-5];
  796.  
  797.         rsum = rsum - ((int)(d>>16)&0xff) + r0;
  798.         gsum = gsum - ((int)(d>> 8)&0xff) + g0;
  799.         bsum = bsum - ((int)(d    )&0xff) + b0;
  800.  
  801.         *dst++ = ((rsum/5) << 16) | ((gsum/5)<<8) | (bsum/5);
  802.  
  803.         ++src;
  804.     } while(--w);
  805. #endif
  806. }
  807.  
  808. static void avgrow_null(Pixel *dst, Pixel *src, long width) {
  809.     memset(dst, 0, width*sizeof(Pixel));
  810. }
  811.  
  812.  
  813. static void __declspec(naked) final_mmx(Pixel *dst, int width, byte **row_array, Pixel **avg_array) {
  814.     static __int64 add4=0x0004000400040004i64;
  815.     static __int64 add8=0x0008000800080008i64;
  816.     static __int64 add16=0x0010001000100010i64;
  817.  
  818.     __asm {
  819.         push        ebx
  820.         push        esi
  821.         push        edi
  822.         push        ebp
  823.  
  824.         mov            esi,[esp+4+16]
  825.         mov            ebp,[esp+8+16]
  826.         mov            edi,[esp+12+16]
  827.         mov            edx,[esp+16+16]
  828.         mov            eax,ebp
  829.         neg            ebp
  830.         shl            eax,2
  831.         add            esi,eax
  832.         pxor        mm7,mm7
  833.  
  834. pixelloop:
  835.         mov            eax,[edx+4]
  836.         movd        mm0,[eax+ebp*4]
  837.         punpcklbw    mm0,mm7
  838.         mov            eax,[edx+8]
  839.         movd        mm2,[eax+ebp*4]
  840.         punpcklbw    mm2,mm7
  841.         paddw        mm0,mm2
  842.         mov            eax,[edx+12]
  843.         movd        mm2,[eax+ebp*4]
  844.         punpcklbw    mm2,mm7
  845.         paddw        mm0,mm2
  846.         paddw        mm0,mm0
  847.         mov            eax,[edx+0]
  848.         movd        mm1,[eax+ebp*4]
  849.         punpcklbw    mm1,mm7
  850.         mov            eax,[edx+16]
  851.         movd        mm3,[eax+ebp*4]
  852.         punpcklbw    mm3,mm7
  853.         paddw        mm1,mm3
  854.         paddw        mm0,mm1
  855.  
  856.         xor            eax,eax
  857.         xor            ebx,ebx
  858.  
  859.         mov            ecx,[edi+0]
  860.         mov            al,[ecx+ebp]
  861.         mov            ecx,[edi+16]
  862.         mov            bl,[ecx+ebp]
  863.         add            eax,ebx
  864.         and            eax,0fffffff0h
  865.  
  866.         mov            ecx,[edi+4]
  867.         mov            bl,[ecx+ebp]
  868.         add            eax,ebx
  869.         mov            ecx,[edi+8]
  870.         mov            bl,[ecx+ebp]
  871.         add            eax,ebx
  872.         mov            ecx,[edi+12]
  873.         mov            bl,[ecx+ebp]
  874.         add            eax,ebx
  875.  
  876.         mov            ebx,eax
  877.         and            al,31
  878.  
  879.         cmp            al,3
  880.         ja            high_detail
  881.         cmp            al,1
  882.         ja            medium_detail
  883.         cmp            ebx,00000080h
  884.         jae            low_detail
  885.  
  886.         paddw        mm0,add4
  887.         psraw        mm0,3
  888.         packuswb    mm0,mm0
  889.         movd        [esi+ebp*4],mm0
  890.         jmp            high_detail
  891.         align        16
  892.  
  893. low_detail:
  894.         movd        mm1,[esi+ebp*4]
  895.         punpcklbw    mm1,mm7
  896.         psllw        mm1,3
  897.         paddw        mm0,mm1
  898.         paddw        mm1,mm1
  899.         paddw        mm0,mm1
  900.         paddw        mm0,add16
  901.         psraw        mm0,5
  902.         packuswb    mm0,mm0
  903.         movd        [esi+ebp*4],mm0
  904.         jmp            short high_detail
  905.  
  906.         align 16
  907. medium_detail:
  908.         movd        mm1,[esi+ebp*4]
  909.         punpcklbw    mm1,mm7
  910.         psllw        mm1,3
  911.         paddw        mm0,mm1
  912.         paddw        mm0,add8
  913.         psraw        mm0,4
  914.         packuswb    mm0,mm0
  915.         movd        [esi+ebp*4],mm0
  916. high_detail:
  917.         inc            ebp
  918.         jne            pixelloop
  919.  
  920.         pop            ebp
  921.         pop            edi
  922.         pop            esi
  923.         pop            ebx
  924.  
  925.         ret
  926.     }
  927. }
  928.  
  929.  
  930. static int smoother_run(const FilterActivation *fa, const FilterFunctions *ff) {
  931.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  932.     long w, h, x;
  933.     int g_thresh = mfd->grad_threshold;
  934.     int next_row = 0, next_avg_row = 0;
  935.     Pixel *avg_rows[5];
  936.     byte *row[5];
  937.     int i;
  938.  
  939.     Pixel *src, *srcf, *dst, *avg;
  940.     PixOffset srcf_pitch;
  941.     void (*avgrow_ptr)(Pixel *dst, Pixel *src, long width);
  942.  
  943.     ///////////
  944.  
  945.     if (mfd->pBlurBitmap) {
  946.         mfd->effBlur->run(&mfd->vbBlur, &fa->src);
  947.         srcf = mfd->vbBlur.data;
  948.         srcf_pitch = mfd->vbBlur.pitch;
  949.  
  950.     } else {
  951.         srcf = fa->src.data;
  952.         srcf_pitch = fa->src.pitch;
  953.     }
  954.  
  955. //    avgrow_ptr = avgrow_null;
  956.     avgrow_ptr = avgrow;
  957.  
  958. //    memcpy(avg_rows, mfd->avg_row, sizeof(Pixel)*5);
  959.  
  960.     avgrow_ptr(mfd->avg_row[1], (Pixel *)((char *)fa->src.data + 0*fa->src.pitch), fa->src.w);
  961.     memcpy(mfd->avg_row[2], mfd->avg_row[1], fa->src.w*4);
  962.     memcpy(mfd->avg_row[3], mfd->avg_row[1], fa->src.w*4);
  963.     avgrow_ptr(mfd->avg_row[4], (Pixel *)((char *)fa->src.data + 1*fa->src.pitch), fa->src.w);
  964.  
  965. //    src = (Pixel *)((char *)fa->src.data + fa->src.pitch);
  966. //    dst = (Pixel *)((char *)fa->dst.data + fa->dst.pitch);
  967.     src = fa->src.data;
  968.     dst = fa->dst.data;
  969.  
  970.     memset(mfd->sum_row[1], 0, fa->dst.w+2);
  971.     memset(mfd->sum_row[2], 0, fa->dst.w+2);
  972.     memset(mfd->sum_row[3], 0, fa->dst.w+2);
  973. //    filtrow_1(mfd->sum_row[3], src+1, fa->dst.w-2, fa->src.pitch, g_thresh);
  974.     filtrow_1(mfd->sum_row[4], (Pixel *)((char *)(srcf + 1) + srcf_pitch), fa->dst.w-2, srcf_pitch, g_thresh);
  975.  
  976.     h = fa->src.h;
  977.     do {
  978.         if (h>3)
  979.             filtrow_1(mfd->sum_row[next_row], (Pixel *)((char *)(srcf + 1) + srcf_pitch*2), fa->dst.w-2, srcf_pitch, g_thresh);
  980.         else
  981.             memset(mfd->sum_row[next_row], 0, fa->dst.w + 2);
  982.  
  983.         avg = mfd->avg_row[next_avg_row];
  984.  
  985.         if (h>2)
  986.             avgrow_ptr(avg, (Pixel *)((char *)src + 2*fa->src.pitch), fa->src.w);
  987.         else
  988.             memcpy(avg, mfd->avg_row[(next_avg_row+4)%5], fa->src.w*4);
  989.  
  990.         if (++next_row>=5)
  991.             next_row = 0;
  992.  
  993.         if (++next_avg_row>=5)
  994.             next_avg_row = 0;
  995.  
  996.         if (MMX_enabled) {
  997.             for(i=0; i<5; i++)
  998.                 row[i] = mfd->sum_row[(next_row+i) % 5] + fa->src.w;
  999.  
  1000.             for(i=0; i<5; i++)
  1001.                 avg_rows[i] = mfd->avg_row[(next_avg_row+i) % 5] + fa->src.w;
  1002.  
  1003.             final_mmx(dst, fa->dst.w, row, avg_rows);
  1004.  
  1005.             src = (Pixel *)((char *)src + fa->src.pitch);
  1006.             dst = (Pixel *)((char *)dst + fa->dst.pitch);
  1007.             srcf = (Pixel *)((char *)srcf + srcf_pitch);
  1008.         } else {
  1009.             for(i=0; i<5; i++)
  1010.                 row[i] = mfd->sum_row[(next_row+i) % 5];
  1011.  
  1012.             for(i=0; i<5; i++)
  1013.                 avg_rows[i] = mfd->avg_row[(next_avg_row+i) % 5];
  1014.  
  1015.             w = fa->src.w;
  1016.             x=0;
  1017.             do {
  1018.                 Pixel p0, p1, p2, p3, p4;
  1019.                 int r, g, b;
  1020.                 int s, A, B;
  1021.  
  1022.                 // bbb000aa
  1023.                 //
  1024.                 // B = 5-neighbor count (0-5)
  1025.                 // A = 3-neighbor count (0-3)
  1026.  
  1027.                 s = (int)(row[0][x]&0xe0) + (int)row[1][x] + (int)row[2][x] + (int)row[3][x] + (int)(row[4][x] & 0xe0);
  1028.                 A = s & 31;
  1029.                 B = s>>5;
  1030.  
  1031.     #if 0
  1032.                 if (A>3)
  1033.                     *dst = 0x00ff00;
  1034.                 else if (A>1)
  1035.                     *dst = 0xff0000;
  1036.                 else if (B>3)
  1037.                     *dst = 0x0000ff;
  1038.                 else
  1039.                     *dst = 0;
  1040.     #else
  1041.                 if (A>3)
  1042.                     *dst = *src;
  1043.                 else {
  1044.                     p0 = avg_rows[0][x];
  1045.                     p1 = avg_rows[1][x];
  1046.                     p2 = avg_rows[2][x];
  1047.                     p3 = avg_rows[3][x];
  1048.                     p4 = avg_rows[4][x];
  1049.  
  1050.                     r = (p0&0xff0000)
  1051.                       + (p1&0xff0000)*2
  1052.                       + (p2&0xff0000)*2
  1053.                       + (p3&0xff0000)*2
  1054.                       + (p4&0xff0000); 
  1055.                     g = (p0&0xff00)
  1056.                       + (p1&0xff00)*2
  1057.                       + (p2&0xff00)*2
  1058.                       + (p3&0xff00)*2
  1059.                       + (p4&0xff00);
  1060.                     b = (p0&0xff)
  1061.                       + (p1&0xff)*2
  1062.                       + (p2&0xff)*2
  1063.                       + (p3&0xff)*2
  1064.                       + (p4&0xff);
  1065.  
  1066.                     if (A>1) {
  1067.                         Pixel d = *src;
  1068.  
  1069.                         r += (d<<3)&0x7f80000;
  1070.                         g += (d<<3)&0x7f800;
  1071.                         b += (d<<3)&0x7f8;
  1072.  
  1073.                         *dst = ((r>>4)&0xff0000) | ((g>>4)&0xff00) | (b>>4);
  1074.                     } else if (B>3) {
  1075.                         Pixel d = *src;
  1076.  
  1077.                         r = r*3 + ((d<<3)&0x7f80000);
  1078.                         g = g*3 + ((d<<3)&0x7f800);
  1079.                         b = b*3 + ((d<<3)&0x7f8);
  1080.  
  1081.                         *dst = ((r>>5)&0xff0000) | ((g>>5)&0xff00) | (b>>5);
  1082.                     } else {
  1083.                         *dst = ((r>>3)&0xff0000) | ((g>>3)&0xff00) | (b>>3);
  1084.                     }
  1085.                 }
  1086.     #endif
  1087.  
  1088.                 ++src;
  1089.                 ++dst;
  1090.  
  1091.             } while(++x<w);
  1092.             src = (Pixel *)((char *)src + fa->src.modulo);
  1093.             dst = (Pixel *)((char *)dst + fa->dst.modulo);
  1094.             srcf = (Pixel *)((char *)srcf + srcf_pitch);
  1095.         }
  1096. //        dst+=2;
  1097. //        src+=2;
  1098.  
  1099.     } while(--h>0);
  1100.  
  1101. #ifdef USE_ASM
  1102.     if (MMX_enabled)
  1103.         __asm emms
  1104. #endif
  1105.  
  1106.     return 0;
  1107. }
  1108.  
  1109. long smoother_param(FilterActivation *fa, const FilterFunctions *ff) {
  1110.     fa->dst.offset    = fa->src.offset;
  1111.     fa->dst.modulo    = fa->src.modulo;
  1112.     fa->dst.pitch    = fa->src.pitch;
  1113.     return 0;
  1114. }
  1115.  
  1116. static int smoother_start(FilterActivation *fa, const FilterFunctions *ff) {
  1117.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1118.     int i;
  1119.  
  1120.     if (!init_count++) {
  1121.         if (!(square_table = new int[765*2+1]))
  1122.             return 1;
  1123.  
  1124.         for(i=0; i<=765; i++)
  1125.             square_table[765+i] = square_table[765-i] = i*i;
  1126.     }
  1127.  
  1128.     for(i=0; i<5; i++)
  1129.         if (!(mfd->sum_row[i] = new byte[fa->src.w+2]))
  1130.             return 1;
  1131.  
  1132.     for(i=0; i<5; i++)
  1133.         if (!(mfd->avg_row[i] = new Pixel[fa->src.w]))
  1134.             return 1;
  1135.  
  1136.     if (mfd->fBlurPass) {
  1137.         if (!(mfd->pBlurBitmap = VirtualAlloc(NULL, ((fa->src.w+1)&-2)*fa->src.h*4, MEM_COMMIT, PAGE_READWRITE)))
  1138.             return 1;
  1139.  
  1140.         mfd->vbBlur = VBitmap(mfd->pBlurBitmap, fa->src.w, fa->src.h, 32);
  1141.  
  1142.         if (!(mfd->effBlur = VCreateEffectBlur(&fa->src)))
  1143.             return 1;
  1144.     }
  1145.  
  1146.     return 0;
  1147. }
  1148.  
  1149. static int smoother_end(FilterActivation *fa, const FilterFunctions *ff) {
  1150.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1151.     int i;
  1152.  
  1153.     if (!--init_count) {
  1154.         delete square_table;
  1155.         square_table = NULL;
  1156.     }
  1157.  
  1158.     for(i=0; i<3; i++) {
  1159.         delete mfd->sum_row[i];
  1160.         mfd->sum_row[i] = NULL;
  1161.     }
  1162.  
  1163.     for(i=0; i<5; i++) {
  1164.         delete mfd->avg_row[i];
  1165.         mfd->avg_row[i] = NULL;
  1166.     }
  1167.  
  1168.     if (mfd->pBlurBitmap) {
  1169.         VirtualFree(mfd->pBlurBitmap, 0, MEM_RELEASE);
  1170.         mfd->pBlurBitmap = NULL;
  1171.     }
  1172.  
  1173.     delete mfd->effBlur; mfd->effBlur = NULL;
  1174.  
  1175.     return 0;
  1176. }
  1177.  
  1178. static BOOL APIENTRY FilterValueDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam) {
  1179.     MyFilterData *mfd = (MyFilterData *)GetWindowLong(hDlg, DWL_USER);
  1180.  
  1181.     switch (message)
  1182.     {
  1183.         case WM_INITDIALOG:
  1184.             mfd = (MyFilterData *)lParam;
  1185.             SendMessage(GetDlgItem(hDlg, IDC_SLIDER), TBM_SETRANGE, (WPARAM)FALSE, MAKELONG(0, 100));
  1186.             SendMessage(GetDlgItem(hDlg, IDC_SLIDER), TBM_SETPOS, (WPARAM)TRUE, (mfd->grad_threshold+100)/200); 
  1187.             CheckDlgButton(hDlg, IDC_PREFILTER, mfd->fBlurPass?BST_CHECKED:BST_UNCHECKED);
  1188.             SetWindowLong(hDlg, DWL_USER, (LONG)mfd);
  1189.             mfd->ifp->InitButton(GetDlgItem(hDlg, IDC_PREVIEW));
  1190.             return (TRUE);
  1191.  
  1192.         case WM_COMMAND:
  1193.             switch(LOWORD(wParam)) {
  1194.             case IDOK:
  1195.                 EndDialog(hDlg, 0);
  1196.                 return TRUE;
  1197.             case IDCANCEL:
  1198.                 EndDialog(hDlg, 1);  
  1199.                 return TRUE;
  1200.             case IDC_PREVIEW:
  1201.                 mfd->ifp->Toggle(hDlg);
  1202.                 break;
  1203.             case IDC_PREFILTER:
  1204.                 if (HIWORD(wParam) == BN_CLICKED) {
  1205.                     mfd->fBlurPass = !!IsDlgButtonChecked(hDlg, IDC_PREFILTER);
  1206.                     mfd->ifp->UndoSystem();
  1207.                     mfd->ifp->RedoSystem();
  1208.                 }
  1209.                 break;
  1210.             }
  1211.             break;
  1212.  
  1213.         case WM_NOTIFY:
  1214.             {
  1215.                 HWND hwndItem = GetDlgItem(hDlg, IDC_SLIDER);
  1216.                 SetDlgItemInt(hDlg, IDC_VALUE, SendMessage(hwndItem, TBM_GETPOS, 0,0), FALSE);
  1217.                 mfd->grad_threshold = SendMessage(GetDlgItem(hDlg, IDC_SLIDER), TBM_GETPOS, 0,0)*200;
  1218.                 if (!mfd->grad_threshold)
  1219.                     ++mfd->grad_threshold;
  1220.                 mfd->ifp->RedoFrame();
  1221.             }
  1222.             return TRUE;
  1223.     }
  1224.     return FALSE;
  1225. }
  1226.  
  1227. static int smoother_config(FilterActivation *fa, const FilterFunctions *ff, HWND hWnd) {
  1228.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1229.     MyFilterData mfd_old = *mfd;
  1230.  
  1231.     mfd->ifp = fa->ifp;
  1232.  
  1233.     if (DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER_SMOOTHER), hWnd, FilterValueDlgProc, (LPARAM)mfd)) {
  1234.         *mfd = mfd_old;
  1235.         return 1;
  1236.     }
  1237.  
  1238.     return 0;
  1239. }
  1240.  
  1241. static void smoother_string(const FilterActivation *fa, const FilterFunctions *ff, char *buf) {
  1242.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1243.  
  1244.     wsprintf(buf, " (g:%ld)", mfd->grad_threshold/4);
  1245. }
  1246.  
  1247. static void smoother_script_config(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc) {
  1248.     FilterActivation *fa = (FilterActivation *)lpVoid;
  1249.     int lv = argv[0].asInt();
  1250.  
  1251.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1252.  
  1253.     mfd->grad_threshold = lv*4;
  1254.     mfd->fBlurPass = !!argv[1].asInt();
  1255. }
  1256.  
  1257. static ScriptFunctionDef smoother_func_defs[]={
  1258.     { (ScriptFunctionPtr)smoother_script_config, "Config", "0ii" },
  1259.     { NULL },
  1260. };
  1261.  
  1262. static CScriptObject smoother_obj={
  1263.     NULL, smoother_func_defs
  1264. };
  1265.  
  1266. static bool smoother_script_line(FilterActivation *fa, const FilterFunctions *ff, char *buf, int buflen) {
  1267.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1268.  
  1269.     _snprintf(buf, buflen, "Config(%d,%d)", mfd->grad_threshold/4, mfd->fBlurPass);
  1270.  
  1271.     return true;
  1272. }
  1273.  
  1274. FilterDefinition filterDef_smoother={
  1275.     0,0,NULL,
  1276.     "smoother",
  1277.     "Dynamically smooths an image while trying not to smear edges.\n\n[Assembly optimized][MMX optimized]",
  1278.     NULL,NULL,
  1279.     sizeof(MyFilterData),
  1280.     NULL,NULL,
  1281.     smoother_run,
  1282.     smoother_param,
  1283.     smoother_config,
  1284.     smoother_string,
  1285.     smoother_start,
  1286.     smoother_end,
  1287.  
  1288.     &smoother_obj,
  1289.     smoother_script_line,
  1290. };